package org.jeecg.common.system.base.controller;

import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.IService;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.beanutils.PropertyUtils;
import org.jeecg.common.api.vo.Result;
import org.jeecg.common.constant.CommonConstant;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.base.entity.IdBaseEntity;
import org.jeecg.common.system.query.QueryGenerator;
import org.jeecg.common.util.ImportExcelUtil;
import org.jeecg.common.util.oConvertUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.web.servlet.ModelAndView;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.lang.reflect.ParameterizedType;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.atomic.AtomicInteger;

/**
 * @Description: Controller基类
 * @Author: dangzhenghui@163.com
 * @Date: 2019-4-21 8:13
 * @Version: 1.0
 */
@Slf4j
public abstract class JeecgBaseController<VO extends IdBaseEntity, T extends IdBaseEntity, S extends IService<T>> extends BaseController<VO> {

    @Autowired
    protected S service;

    /**
     * 导出excel
     *
     * @param request
     */
    protected ModelAndView exportXls(HttpServletRequest request, T object, Class<VO> clazz, String title) {

        // Step.1 获取导出数据
        List<T> pageList;
        String selections = request.getParameter("selections");
        if (oConvertUtils.isNotEmpty(selections)) {
            List<String> selectionList = Arrays.asList(selections.split(CommonConstant.DEFAULT_SEPARATOR));
            QueryWrapper<T> queryWrapper = new QueryWrapper<>();
            queryWrapper.in("id", selectionList);
            pageList = service.list(queryWrapper);
        } else {
            QueryWrapper<T> queryWrapper = QueryGenerator.initQueryWrapper(object, request.getParameterMap());
            pageList = service.list(queryWrapper);
        }

        // Step.2 组装pageList
        List<VO> exportList = this.exportList(pageList);
        return super.exportXls(title, exportList, clazz, true);
    }


    /**
     * 获取对象ID
     *
     * @return
     */
    private String getId(T item) {
        try {
            return PropertyUtils.getProperty(item, "id").toString();
        } catch (Exception e) {
            e.printStackTrace();
            return null;
        }
    }

    /**
     * 通过excel导入数据
     *
     * @param request
     * @param response
     * @return
     */
    protected Result<?> importExcel(HttpServletRequest request, HttpServletResponse response, Class<VO> clazz) {
        try {
            List<VO> list = super.importExcelBase(request, response, clazz);
            //update-begin-author:taoyan date:20190528 for:批量插入数据
            long start = System.currentTimeMillis();

            // 错误信息
            List<String> errorMessage = new ArrayList<>();
            AtomicInteger successLines = new AtomicInteger();
            AtomicInteger errorLines = new AtomicInteger();

            list.stream().forEach(vo -> {
                try {
                    boolean bool = this.importSave(vo);
                    if (bool) {
                        successLines.getAndIncrement();
                    } else {
                        errorLines.getAndIncrement();
                        //                            errorMessage.add("导入失败:" + JSON.toJSONString(vo));
                        errorMessage.add("第" + vo.getRowNumber() + "行数据：导入失败。");
                    }
                } catch (JeecgBootException e) {
                    errorLines.getAndIncrement();
                    errorMessage.add("第" + vo.getRowNumber() + "行数据：" + e.getMessage() + "。");
                    //                        errorMessage.add("导入失败:" + e.getMessage() + "-" + JSON.toJSONString(vo));
                } catch (Exception e) {
                    errorLines.getAndIncrement();
                    log.error(e.getMessage(), e);
                    errorMessage.add("第" + vo.getRowNumber() + "行数据：导入失败。");
                    //                        errorMessage.add("导入失败:" + e.getMessage() + "-" + JSON.toJSONString(vo));
                }
            });
            log.info("消耗时间" + (System.currentTimeMillis() - start) + "毫秒");
            return ImportExcelUtil.imporReturnRes(errorLines.get(), successLines.get(), errorMessage);
        } catch (Exception e) {
            e.printStackTrace();
            return Result.error("文件导入失败！" + e.getMessage());
        }
//        return Result.error("文件导入失败！");
    }


    public abstract List<VO> exportList(List<T> list);
    /* {
//        return JSON.parseObject(JSON.toJSONStringWithDateFormat(list, DateUtils.DATE_FORMAT, SerializerFeature.WriteDateUseDateFormat), new TypeReference<List<VO>>(){});

        return JSON.parseObject(JSON.toJSONString(list), new TypeReference<List<VO>>(){});
    }*/

    public abstract boolean importSave(VO vo);/* {
        T A = newT();
        BeanUtils.copyProperties(vo, A);
        return service.save(A);
    }*/

    public T newT() {
        try {
            // 通过反射获取model的真实类型
            ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
            Class<T> clazz = (Class<T>) pt.getActualTypeArguments()[0];
            // 通过反射创建model的实例
            return clazz.newInstance();
        } catch (Exception e) {
//            throw new RuntimeException(e);
        }
        return null;
    }

    public VO newVO() {
        try {
            // 通过反射获取model的真实类型
            ParameterizedType pt = (ParameterizedType) this.getClass().getGenericSuperclass();
            Class<VO> clazz = (Class<VO>) pt.getActualTypeArguments()[0];
            // 通过反射创建model的实例
            return clazz.newInstance();
        } catch (Exception e) {
//            throw new RuntimeException(e);
        }
        return null;
    }
}
